﻿module Tile

open SI
open Math
open Casanova
type Tile = 
    {
        mID : int
        mutable mPosition : Vector2<tile>
        mType : TILE_TYPE
        mutable mOrientation : ORIENTATION
        mDimension : float32<pixel>
    }

    static member Init( iId, iPosition, iType, iOrientation, iTileLenght) = 
        let temp = 
            {
                mID             = iId
                mPosition       = iPosition
                mType           = iType
                mOrientation    = iOrientation
                mDimension      = iTileLenght
            }
        temp

    member this.Update( iRow,  iColumn, iOrientation) = 
        let pos = new Vector2<tile>(iRow, iColumn) 
        this.mPosition <- pos
        this.mOrientation <- iOrientation
            

    member this.TieEntrance() = 
        let mutable res = [| ORIENTATION.N; ORIENTATION.N; ORIENTATION.N |]
        let orientation = this.mOrientation
        if (ORIENTATION.N = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.E
            res.[2] <- ORIENTATION.W
        else if (ORIENTATION.E = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.S
            res.[2] <- ORIENTATION.N
        else if (ORIENTATION.W = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.S
            res.[2] <- ORIENTATION.N
        else
            res.[0] <- orientation
            res.[1] <- ORIENTATION.E
            res.[2] <- ORIENTATION.W
        res

    member this.StreightEntrance() = 
        let mutable res = [| ORIENTATION.N; ORIENTATION.N; ORIENTATION.N |]
        let orientation = this.mOrientation
        if (ORIENTATION.N = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.S
            res.[2] <- orientation
        else if (ORIENTATION.S = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.N
            res.[2] <- orientation
        else if (ORIENTATION.E = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.W
            res.[2] <- orientation
        else
            res.[0] <- orientation
            res.[1] <- ORIENTATION.E
            res.[2] <- orientation
        res

    member this.CurvedEntrance() = 
        let mutable res = [| ORIENTATION.N; ORIENTATION.N; ORIENTATION.N |]
        let orientation = this.mOrientation
        if (ORIENTATION.N = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.E
            res.[2] <- orientation
        else if (ORIENTATION.E = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.S
            res.[2] <- orientation
        else if(ORIENTATION.W = orientation) then
            res.[0] <- orientation
            res.[1] <- ORIENTATION.N
            res.[2] <- orientation
        else
            res.[0] <- orientation
            res.[1] <- ORIENTATION.W
            res.[2] <- orientation
        res

    member this.IsTileCloseTo(iOther) = 
        let actualPos = this.mPosition
        let otherPos = iOther.mPosition
        let rowDistance = actualPos.X - otherPos.X
        let columnDistance = actualPos.Y - otherPos.Y

        let mutable res = POSITION.None

        if (1.f<tile> = rowDistance && 0.f<tile> = columnDistance) then
            res <- POSITION.Up
        if (-1.f<tile> = rowDistance && 0.f<tile> = columnDistance) then
            res <- POSITION.Down
        if (0.f<tile> = rowDistance && 1.f<tile> = columnDistance) then
            res <- POSITION.Left
        if (0.f<tile> = rowDistance && -1.f<tile> = columnDistance) then
            res <- POSITION.Right
        res

    member this.IsTileConnected(iOther) = 
        let relativePos = this.IsTileCloseTo(iOther)
        if (POSITION.None = relativePos) then 
            false
        else
            let mutable myEntrance = [||]
            let mutable otherEntrace = [||]

            let mutable res = false

            if this.mType = TILE_TYPE.Curved then
                myEntrance <- this.CurvedEntrance()
            else if this.mType = TILE_TYPE.Corner then
                myEntrance <- this.CurvedEntrance()   
            else if this.mType = TILE_TYPE.Tie then
                myEntrance <- this.TieEntrance();
            else
                myEntrance <- this.StreightEntrance()

            if iOther.mType = TILE_TYPE.Curved then
                otherEntrace <- iOther.CurvedEntrance()
            else  if iOther.mType = TILE_TYPE.Corner then
                otherEntrace <- iOther.CurvedEntrance()   
            else if iOther.mType = TILE_TYPE.Tie then
                otherEntrace <- iOther.TieEntrance();
            else
                otherEntrace <- iOther.StreightEntrance()

            if relativePos = POSITION.Up then
                if (ORIENTATION.N = myEntrance.[0] || ORIENTATION.N = myEntrance.[1] || ORIENTATION.N = myEntrance.[2]) then
                    if (ORIENTATION.S = otherEntrace.[0] || ORIENTATION.S = otherEntrace.[1] || ORIENTATION.S = otherEntrace.[2]) then
                        res <- true
            else if relativePos = POSITION.Down then
                if (ORIENTATION.S = myEntrance.[0] || ORIENTATION.S = myEntrance.[1] || ORIENTATION.S = myEntrance.[2]) then
                    if (ORIENTATION.N = otherEntrace.[0] || ORIENTATION.N = otherEntrace.[1] || ORIENTATION.N = otherEntrace.[2]) then
                        res <- true
            else if relativePos = POSITION.Left then
                if (ORIENTATION.W = myEntrance.[0] || ORIENTATION.W = myEntrance.[1] || ORIENTATION.W = myEntrance.[2]) then
                    if (ORIENTATION.E = otherEntrace.[0] || ORIENTATION.E = otherEntrace.[1] || ORIENTATION.E = otherEntrace.[2]) then
                        res <- true
            else if (ORIENTATION.E = myEntrance.[0] || ORIENTATION.E = myEntrance.[1] || ORIENTATION.E = myEntrance.[2]) then
                if (ORIENTATION.W = otherEntrace.[0] || ORIENTATION.W = otherEntrace.[1] || ORIENTATION.W = otherEntrace.[2]) then
                    res <- true
            res
    
    override this.ToString() = 
        let idS = "ID: " + this.mID.ToString()
        let posS = ", Pos: " + this.mPosition.X.ToString() + ", " + this.mPosition.Y.ToString()
        let orS = ", Or: " + this.mOrientation.ToString()
        let typeS = ", Type: " + this.mType.ToString()
        idS + posS + orS + typeS
    